#!/usr/bin/env python
from configobj import ConfigObj
import MySQLdb
import time
import threading
import socket
import pickle
from Sms import *
from DTOSurvey import *
from Loadbalancer import *

POINTS_FOR_SURVEY = 1

class DBReader(threading.Thread):
    def __init__(self):
	threading.Thread.__init__(self)
	self._readConfig()
	self._connectToDb()
	self._loadbalancer = Loadbalancer()
    def _readConfig(self):
	config = ConfigObj("config")
	self._dbHost = config['database']['host']
	self._dbUser = config['database']['user']
	self._dbPassword = config['database']['password'] 
	self._dbDB = config['database']['db']
    def _connectToDb(self):
	self._db = MySQLdb.connect( 
		host = self._dbHost, 
		user = self._dbUser, 
		passwd = self._dbPassword, 
		db = self._dbDB )
	self._cursor = self._db.cursor()
    def getFirstUnsentSurveyId(self):
	self._cursor = self._db.cursor()
	self._cursor.execute("select surveyId \
		from surveys \
		where state=1 limit 1")
	row = self._cursor.fetchone()
	if row==None:
	    # without next line program didnt know about changes in db
	    self._db.commit()
	    return None
	else:
	    return row[0]
    def _finishedSending(self, surveyId):
	self._cursor = self._db.cursor()
	print "DBReader: changing state of survey [%s] to sent" %surveyId
	self._cursor.callproc('changeSurveyState', [surveyId, 2])
	self._db.commit()
    def _getParticipantsForSurvey(self, surveyId):
	self._cursor = self._db.cursor()
	self._cursor.callproc('getParticipantForSurvey', [surveyId])
	participantsList = []
	while 1:
	    row = self._cursor.fetchone()
	    if row is None:
		break
	    participantsList.append(str(row[0]))
	return participantsList
    def _getQuestion(self, surveyId):
	self._cursor = self._db.cursor()
	self._cursor.callproc('getSurvey', [surveyId])
	survey = self._cursor.fetchone()
	return survey[2]; # surveys.question
    def getDTOSurvey(self, surveyId):
	participantsList = self._getParticipantsForSurvey(surveyId)
	dtoSurvey = DTOSurvey(surveyId, self._getQuestion(surveyId))
	for participant in participantsList:
	    dtoSurvey.addPhoneNumber(participant)
	#print "DBReader: formed survey [%s]" %dtoSurvey
	return dtoSurvey
    def putPickledSmsInDatabase(self, pickledSms):
	sms = pickle.loads(pickledSms)
	print "DBReader: putting in db [%s]" %sms
	try: 
	    surveyId = sms.getSurveyId()
	    answer = sms.getAnswer()
	    customerPhone = sms.getNumber()
	except Exception, e:
	    # means that sms is not syntax friendly
	    print e
	    return
	# checking if answer is in correct range
	self._cursor = self._db.cursor()
	range = self._getNumOfPossibleAnswers(surveyId)
	if self._isAnswerCorrect(answer, range):
	    self._cursor.callproc('submitAnswer', 
		    [surveyId, answer, customerPhone, POINTS_FOR_SURVEY])
	    self._db.commit();
	else:
	    print "DBReader: wrong answer from user [%s]" %customerPhone
    def _getNumOfPossibleAnswers(self, surveyId):
	self._cursor.execute("select numOfPossibleAnswers \
		from surveys \
		where surveyId=%s", [surveyId])
	row = self._cursor.fetchone()
	return row[0]
    def _isAnswerCorrect(self, answer, numOfPossibleAnswers):
	if int(numOfPossibleAnswers) is 0:
	    return True
	elif int(answer)>0 and int(answer)<=int(numOfPossibleAnswers):
	    return True
	else:
	    return False
    def _getFromLoadbalancer(self):
	#TODO: nonblocking socket
	pass
    def run(self):
	# wait for connection from loadbalancer
	self._loadbalancer.waitForConnection()
	while 1:
	    id = self.getFirstUnsentSurveyId()
	    if id is None: 
		# recv answers from smsmodule
		pickledAnswer = self._loadbalancer.recvFromModule()
		while pickledAnswer:
		    self.putPickledSmsInDatabase(pickledAnswer)
		    pickledAnswer = self._loadbalancer.recvFromModule()
		time.sleep(1)
	    else:
		# send dtoSurvey to smsmodule
		dtoSurvey = self.getDTOSurvey(id)
		self._loadbalancer.sendToModule(dtoSurvey)
		self._finishedSending(id)

def main():
    dbr = DBReader()
    print "DBReader: started"
    dbr.start()
    #sms1 = pickle.dumps(Sms("+4528458981", "q1 3"))
    #dbr.putPickledSmsInDatabase(sms1)
    #sms2 = pickle.dumps(Sms("+4528458981", "q1 2"))
    #dbr.putPickledSmsInDatabase(sms2)
    
if __name__=="__main__":
    main()

